/**
 * QtAwesome - use font-awesome (or other font icons) in your c++ / Qt Application
 *
 * MIT Licensed
 *
 * Copyright 2013-2015 - Reliable Bits Software by Blommers IT. All Rights Reserved.
 * Author Rick Blommers
 */

#include "QtAwesome.h"
#include "QtAwesomeAnim.h"

#include <QDebug>
#include <QFile>
#include <QFontDatabase>



/// The font-awesome icon painter
class QtAwesomeCharIconPainter: public QtAwesomeIconPainter
{
public:
    virtual void paint( QtAwesome* awesome, QPainter* painter, const QRect& rect, QIcon::Mode mode, QIcon::State state, const QVariantMap& options  )
    {
        Q_UNUSED(mode);
        Q_UNUSED(state);
        Q_UNUSED(options);

        painter->save();

        QObject* qanim = qvariant_cast<QObject*>(options.value("anim"));
        QtAwesomeAnimation* anim = qobject_cast<QtAwesomeAnimation*>(qanim);
        if( anim ) {
            anim->setup( *painter, rect );
        }


        // set the correct color
        QColor color = options.value("color").value<QColor>();
        QString text = options.value("text").toString();

        if( mode == QIcon::Disabled ) {
            color = options.value("color-disabled").value<QColor>();
            QVariant alt = options.value("text-disabled");
            if( alt.isValid() ) {
                text = alt.toString();
            }
        } else if( mode == QIcon::Active ) {
            color = options.value("color-active").value<QColor>();
            QVariant alt = options.value("text-active");
            if( alt.isValid() ) {
                text = alt.toString();
            }
        } else if( mode == QIcon::Selected ) {
            color = options.value("color-selected").value<QColor>();
            QVariant alt = options.value("text-selected");
            if( alt.isValid() ) {
                text = alt.toString();
            }
        }
        painter->setPen(color);

        // add some 'padding' around the icon
        int drawSize = qRound(rect.height()*options.value("scale-factor").toFloat());

        painter->setFont( awesome->font(drawSize) );
        painter->drawText( rect, text, QTextOption( Qt::AlignCenter|Qt::AlignVCenter ) );
        painter->restore();
    }

};


//---------------------------------------------------------------------------------------


/// The painter icon engine.
class QtAwesomeIconPainterIconEngine : public QIconEngine
{

public:

    QtAwesomeIconPainterIconEngine( QtAwesome* awesome, QtAwesomeIconPainter* painter, const QVariantMap& options  )
        : awesomeRef_(awesome)
        , iconPainterRef_(painter)
        , options_(options)
    {
    }

    virtual ~QtAwesomeIconPainterIconEngine() {}

    QtAwesomeIconPainterIconEngine* clone() const
    {
        return new QtAwesomeIconPainterIconEngine( awesomeRef_, iconPainterRef_, options_ );
    }

    virtual void paint(QPainter* painter, const QRect& rect, QIcon::Mode mode, QIcon::State state)
    {
        Q_UNUSED( mode );
        Q_UNUSED( state );
        iconPainterRef_->paint( awesomeRef_, painter, rect, mode, state, options_ );
    }

    virtual QPixmap pixmap(const QSize& size, QIcon::Mode mode, QIcon::State state)
    {
        QPixmap pm(size);
        pm.fill( Qt::transparent ); // we need transparency
        {
            QPainter p(&pm);
            paint(&p, QRect(QPoint(0,0),size), mode, state);
        }
        return pm;
    }

private:

    QtAwesome* awesomeRef_;                  ///< a reference to the QtAwesome instance
    QtAwesomeIconPainter* iconPainterRef_;   ///< a reference to the icon painter
    QVariantMap options_;                    ///< the options for this icon painter
};


//---------------------------------------------------------------------------------------

/// The default icon colors
QtAwesome::QtAwesome( QObject* parent )
    : QObject( parent )
    , namedCodepoints_()
{
    // initialize the default options
    setDefaultOption( "color", QColor(50,50,50) );
    setDefaultOption( "color-disabled", QColor(70,70,70,60));
    setDefaultOption( "color-active", QColor(10,10,10));
    setDefaultOption( "color-selected", QColor(10,10,10));
    setDefaultOption( "scale-factor", 0.9 );

    setDefaultOption( "text", QVariant() );
    setDefaultOption( "text-disabled", QVariant() );
    setDefaultOption( "text-active", QVariant() );
    setDefaultOption( "text-selected", QVariant() );

    fontIconPainter_ = new QtAwesomeCharIconPainter();

}


QtAwesome::~QtAwesome()
{
    delete fontIconPainter_;
//    delete errorIconPainter_;
    qDeleteAll(painterMap_);
}

/// initializes the QtAwesome icon factory with the given fontname
void QtAwesome::init(const QString& fontname)
{
    fontName_ = fontname;
}

struct FANameIcon {
  const char *name;
  fa::icon icon;
};

static const FANameIcon faNameIconArray[] = {
    { "fa_500px"             , fa::fa_500px             },
    { "adjust"               , fa::adjust               },
    { "adn"                  , fa::adn                  },
    { "aligncenter"          , fa::aligncenter          },
    { "alignjustify"         , fa::alignjustify         },
    { "alignleft"            , fa::alignleft            },
    { "alignright"           , fa::alignright           },
    { "amazon"               , fa::amazon               },
    { "ambulance"            , fa::ambulance            },
    { "anchor"               , fa::anchor               },
    { "android"              , fa::android              },
    { "angellist"            , fa::angellist            },
    { "angledoubledown"      , fa::angledoubledown      },
    { "angledoubleleft"      , fa::angledoubleleft      },
    { "angledoubleright"     , fa::angledoubleright     },
    { "angledoubleup"        , fa::angledoubleup        },
    { "angledown"            , fa::angledown            },
    { "angleleft"            , fa::angleleft            },
    { "angleright"           , fa::angleright           },
    { "angleup"              , fa::angleup              },
    { "apple"                , fa::apple                },
    { "archive"              , fa::archive              },
    { "areachart"            , fa::areachart            },
    { "arrowcircledown"      , fa::arrowcircledown      },
    { "arrowcircleleft"      , fa::arrowcircleleft      },
    { "arrowcircleodown"     , fa::arrowcircleodown     },
    { "arrowcircleoleft"     , fa::arrowcircleoleft     },
    { "arrowcircleoright"    , fa::arrowcircleoright    },
    { "arrowcircleoup"       , fa::arrowcircleoup       },
    { "arrowcircleright"     , fa::arrowcircleright     },
    { "arrowcircleup"        , fa::arrowcircleup        },
    { "arrowdown"            , fa::arrowdown            },
    { "arrowleft"            , fa::arrowleft            },
    { "arrowright"           , fa::arrowright           },
    { "arrowup"              , fa::arrowup              },
    { "arrows"               , fa::arrows               },
    { "arrowsalt"            , fa::arrowsalt            },
    { "arrowsh"              , fa::arrowsh              },
    { "arrowsv"              , fa::arrowsv              },
    { "asterisk"             , fa::asterisk             },
    { "at"                   , fa::at                   },
    { "automobile"           , fa::automobile           },
    { "backward"             , fa::backward             },
    { "balancescale"         , fa::balancescale         },
    { "ban"                  , fa::ban                  },
    { "bank"                 , fa::bank                 },
    { "barchart"             , fa::barchart             },
    { "barcharto"            , fa::barcharto            },
    { "barcode"              , fa::barcode              },
    { "bars"                 , fa::bars                 },
    { "battery0"             , fa::battery0             },
    { "battery1"             , fa::battery1             },
    { "battery2"             , fa::battery2             },
    { "battery3"             , fa::battery3             },
    { "battery4"             , fa::battery4             },
    { "batteryempty"         , fa::batteryempty         },
    { "batteryfull"          , fa::batteryfull          },
    { "batteryhalf"          , fa::batteryhalf          },
    { "batteryquarter"       , fa::batteryquarter       },
    { "batterythreequarters" , fa::batterythreequarters },
    { "bed"                  , fa::bed                  },
    { "beer"                 , fa::beer                 },
    { "behance"              , fa::behance              },
    { "behancesquare"        , fa::behancesquare        },
    { "bell"                 , fa::bell                 },
    { "bello"                , fa::bello                },
    { "bellslash"            , fa::bellslash            },
    { "bellslasho"           , fa::bellslasho           },
    { "bicycle"              , fa::bicycle              },
    { "binoculars"           , fa::binoculars           },
    { "birthdaycake"         , fa::birthdaycake         },
    { "bitbucket"            , fa::bitbucket            },
    { "bitbucketsquare"      , fa::bitbucketsquare      },
    { "bitcoin"              , fa::bitcoin              },
    { "blacktie"             , fa::blacktie             },
    { "bluetooth"            , fa::bluetooth            },
    { "bluetoothb"           , fa::bluetoothb           },
    { "bold"                 , fa::bold                 },
    { "bolt"                 , fa::bolt                 },
    { "bomb"                 , fa::bomb                 },
    { "book"                 , fa::book                 },
    { "bookmark"             , fa::bookmark             },
    { "bookmarko"            , fa::bookmarko            },
    { "briefcase"            , fa::briefcase            },
    { "btc"                  , fa::btc                  },
    { "bug"                  , fa::bug                  },
    { "building"             , fa::building             },
    { "buildingo"            , fa::buildingo            },
    { "bullhorn"             , fa::bullhorn             },
    { "bullseye"             , fa::bullseye             },
    { "bus"                  , fa::bus                  },
    { "buysellads"           , fa::buysellads           },
    { "cab"                  , fa::cab                  },
    { "calculator"           , fa::calculator           },
    { "calendar"             , fa::calendar             },
    { "calendarchecko"       , fa::calendarchecko       },
    { "calendarminuso"       , fa::calendarminuso       },
    { "calendaro"            , fa::calendaro            },
    { "calendarpluso"        , fa::calendarpluso        },
    { "calendartimeso"       , fa::calendartimeso       },
    { "camera"               , fa::camera               },
    { "cameraretro"          , fa::cameraretro          },
    { "car"                  , fa::car                  },
    { "caretdown"            , fa::caretdown            },
    { "caretleft"            , fa::caretleft            },
    { "caretright"           , fa::caretright           },
    { "caretsquareodown"     , fa::caretsquareodown     },
    { "caretsquareoleft"     , fa::caretsquareoleft     },
    { "caretsquareoright"    , fa::caretsquareoright    },
    { "caretsquareoup"       , fa::caretsquareoup       },
    { "caretup"              , fa::caretup              },
    { "cartarrowdown"        , fa::cartarrowdown        },
    { "cartplus"             , fa::cartplus             },
    { "cc"                   , fa::cc                   },
    { "ccamex"               , fa::ccamex               },
    { "ccdinersclub"         , fa::ccdinersclub         },
    { "ccdiscover"           , fa::ccdiscover           },
    { "ccjcb"                , fa::ccjcb                },
    { "ccmastercard"         , fa::ccmastercard         },
    { "ccpaypal"             , fa::ccpaypal             },
    { "ccstripe"             , fa::ccstripe             },
    { "ccvisa"               , fa::ccvisa               },
    { "certificate"          , fa::certificate          },
    { "chain"                , fa::chain                },
    { "chainbroken"          , fa::chainbroken          },
    { "check"                , fa::check                },
    { "checkcircle"          , fa::checkcircle          },
    { "checkcircleo"         , fa::checkcircleo         },
    { "checksquare"          , fa::checksquare          },
    { "checksquareo"         , fa::checksquareo         },
    { "chevroncircledown"    , fa::chevroncircledown    },
    { "chevroncircleleft"    , fa::chevroncircleleft    },
    { "chevroncircleright"   , fa::chevroncircleright   },
    { "chevroncircleup"      , fa::chevroncircleup      },
    { "chevrondown"          , fa::chevrondown          },
    { "chevronleft"          , fa::chevronleft          },
    { "chevronright"         , fa::chevronright         },
    { "chevronup"            , fa::chevronup            },
    { "child"                , fa::child                },
    { "chrome"               , fa::chrome               },
    { "circle"               , fa::circle               },
    { "circleo"              , fa::circleo              },
    { "circleonotch"         , fa::circleonotch         },
    { "circlethin"           , fa::circlethin           },
    { "clipboard"            , fa::clipboard            },
    { "clocko"               , fa::clocko               },
    { "clone"                , fa::clone                },
    { "close"                , fa::close                },
    { "cloud"                , fa::cloud                },
    { "clouddownload"        , fa::clouddownload        },
    { "cloudupload"          , fa::cloudupload          },
    { "cny"                  , fa::cny                  },
    { "code"                 , fa::code                 },
    { "codefork"             , fa::codefork             },
    { "codepen"              , fa::codepen              },
    { "codiepie"             , fa::codiepie             },
    { "coffee"               , fa::coffee               },
    { "cog"                  , fa::cog                  },
    { "cogs"                 , fa::cogs                 },
    { "columns"              , fa::columns              },
    { "comment"              , fa::comment              },
    { "commento"             , fa::commento             },
    { "commenting"           , fa::commenting           },
    { "commentingo"          , fa::commentingo          },
    { "comments"             , fa::comments             },
    { "commentso"            , fa::commentso            },
    { "compass"              , fa::compass              },
    { "compress"             , fa::compress             },
    { "connectdevelop"       , fa::connectdevelop       },
    { "contao"               , fa::contao               },
    { "copy"                 , fa::copy                 },
    { "copyright"            , fa::copyright            },
    { "creativecommons"      , fa::creativecommons      },
    { "creditcard"           , fa::creditcard           },
    { "creditcardalt"        , fa::creditcardalt        },
    { "crop"                 , fa::crop                 },
    { "crosshairs"           , fa::crosshairs           },
    { "css3"                 , fa::css3                 },
    { "cube"                 , fa::cube                 },
    { "cubes"                , fa::cubes                },
    { "cut"                  , fa::cut                  },
    { "cutlery"              , fa::cutlery              },
    { "dashboard"            , fa::dashboard            },
    { "dashcube"             , fa::dashcube             },
    { "database"             , fa::database             },
    { "dedent"               , fa::dedent               },
    { "delicious"            , fa::delicious            },
    { "desktop"              , fa::desktop              },
    { "deviantart"           , fa::deviantart           },
    { "diamond"              , fa::diamond              },
    { "digg"                 , fa::digg                 },
    { "dollar"               , fa::dollar               },
    { "dotcircleo"           , fa::dotcircleo           },
    { "download"             , fa::download             },
    { "dribbble"             , fa::dribbble             },
    { "dropbox"              , fa::dropbox              },
    { "drupal"               , fa::drupal               },
    { "edge"                 , fa::edge                 },
    { "edit"                 , fa::edit                 },
    { "eject"                , fa::eject                },
    { "ellipsish"            , fa::ellipsish            },
    { "ellipsisv"            , fa::ellipsisv            },
    { "empire"               , fa::empire               },
    { "envelope"             , fa::envelope             },
    { "envelopeo"            , fa::envelopeo            },
    { "envelopesquare"       , fa::envelopesquare       },
    { "eraser"               , fa::eraser               },
    { "eur"                  , fa::eur                  },
    { "euro"                 , fa::euro                 },
    { "exchange"             , fa::exchange             },
    { "exclamation"          , fa::exclamation          },
    { "exclamationcircle"    , fa::exclamationcircle    },
    { "exclamationtriangle"  , fa::exclamationtriangle  },
    { "expand"               , fa::expand               },
    { "expeditedssl"         , fa::expeditedssl         },
    { "externallink"         , fa::externallink         },
    { "externallinksquare"   , fa::externallinksquare   },
    { "eye"                  , fa::eye                  },
    { "eyeslash"             , fa::eyeslash             },
    { "eyedropper"           , fa::eyedropper           },
    { "facebook"             , fa::facebook             },
    { "facebookf"            , fa::facebookf            },
    { "facebookofficial"     , fa::facebookofficial     },
    { "facebooksquare"       , fa::facebooksquare       },
    { "fastbackward"         , fa::fastbackward         },
    { "fastforward"          , fa::fastforward          },
    { "fax"                  , fa::fax                  },
    { "feed"                 , fa::feed                 },
    { "female"               , fa::female               },
    { "fighterjet"           , fa::fighterjet           },
    { "file"                 , fa::file                 },
    { "filearchiveo"         , fa::filearchiveo         },
    { "fileaudioo"           , fa::fileaudioo           },
    { "filecodeo"            , fa::filecodeo            },
    { "fileexcelo"           , fa::fileexcelo           },
    { "fileimageo"           , fa::fileimageo           },
    { "filemovieo"           , fa::filemovieo           },
    { "fileo"                , fa::fileo                },
    { "filepdfo"             , fa::filepdfo             },
    { "filephotoo"           , fa::filephotoo           },
    { "filepictureo"         , fa::filepictureo         },
    { "filepowerpointo"      , fa::filepowerpointo      },
    { "filesoundo"           , fa::filesoundo           },
    { "filetext"             , fa::filetext             },
    { "filetexto"            , fa::filetexto            },
    { "filevideoo"           , fa::filevideoo           },
    { "filewordo"            , fa::filewordo            },
    { "filezipo"             , fa::filezipo             },
    { "fileso"               , fa::fileso               },
    { "film"                 , fa::film                 },
    { "filter"               , fa::filter               },
    { "fire"                 , fa::fire                 },
    { "fireextinguisher"     , fa::fireextinguisher     },
    { "firefox"              , fa::firefox              },
    { "flag"                 , fa::flag                 },
    { "flagcheckered"        , fa::flagcheckered        },
    { "flago"                , fa::flago                },
    { "flash"                , fa::flash                },
    { "flask"                , fa::flask                },
    { "flickr"               , fa::flickr               },
    { "floppyo"              , fa::floppyo              },
    { "folder"               , fa::folder               },
    { "foldero"              , fa::foldero              },
    { "folderopen"           , fa::folderopen           },
    { "folderopeno"          , fa::folderopeno          },
    { "font"                 , fa::font                 },
    { "fonticons"            , fa::fonticons            },
    { "fortawesome"          , fa::fortawesome          },
    { "forumbee"             , fa::forumbee             },
    { "forward"              , fa::forward              },
    { "foursquare"           , fa::foursquare           },
    { "frowno"               , fa::frowno               },
    { "futbolo"              , fa::futbolo              },
    { "gamepad"              , fa::gamepad              },
    { "gavel"                , fa::gavel                },
    { "gbp"                  , fa::gbp                  },
    { "ge"                   , fa::ge                   },
    { "gear"                 , fa::gear                 },
    { "gears"                , fa::gears                },
    { "genderless"           , fa::genderless           },
    { "getpocket"            , fa::getpocket            },
    { "gg"                   , fa::gg                   },
    { "ggcircle"             , fa::ggcircle             },
    { "gift"                 , fa::gift                 },
    { "git"                  , fa::git                  },
    { "gitsquare"            , fa::gitsquare            },
    { "github"               , fa::github               },
    { "githubalt"            , fa::githubalt            },
    { "githubsquare"         , fa::githubsquare         },
    { "gittip"               , fa::gittip               },
    { "glass"                , fa::glass                },
    { "globe"                , fa::globe                },
    { "google"               , fa::google               },
    { "googleplus"           , fa::googleplus           },
    { "googleplussquare"     , fa::googleplussquare     },
    { "googlewallet"         , fa::googlewallet         },
    { "graduationcap"        , fa::graduationcap        },
    { "gratipay"             , fa::gratipay             },
    { "group"                , fa::group                },
    { "hsquare"              , fa::hsquare              },
    { "hackernews"           , fa::hackernews           },
    { "handgrabo"            , fa::handgrabo            },
    { "handlizardo"          , fa::handlizardo          },
    { "handodown"            , fa::handodown            },
    { "handoleft"            , fa::handoleft            },
    { "handoright"           , fa::handoright           },
    { "handoup"              , fa::handoup              },
    { "handpapero"           , fa::handpapero           },
    { "handpeaceo"           , fa::handpeaceo           },
    { "handpointero"         , fa::handpointero         },
    { "handrocko"            , fa::handrocko            },
    { "handscissorso"        , fa::handscissorso        },
    { "handspocko"           , fa::handspocko           },
    { "handstopo"            , fa::handstopo            },
    { "hashtag"              , fa::hashtag              },
    { "hddo"                 , fa::hddo                 },
    { "header"               , fa::header               },
    { "headphones"           , fa::headphones           },
    { "heart"                , fa::heart                },
    { "hearto"               , fa::hearto               },
    { "heartbeat"            , fa::heartbeat            },
    { "history"              , fa::history              },
    { "home"                 , fa::home                 },
    { "hospitalo"            , fa::hospitalo            },
    { "hotel"                , fa::hotel                },
    { "hourglass"            , fa::hourglass            },
    { "hourglass1"           , fa::hourglass1           },
    { "hourglass2"           , fa::hourglass2           },
    { "hourglass3"           , fa::hourglass3           },
    { "hourglassend"         , fa::hourglassend         },
    { "hourglasshalf"        , fa::hourglasshalf        },
    { "hourglasso"           , fa::hourglasso           },
    { "hourglassstart"       , fa::hourglassstart       },
    { "houzz"                , fa::houzz                },
    { "html5"                , fa::html5                },
    { "icursor"              , fa::icursor              },
    { "ils"                  , fa::ils                  },
    { "image"                , fa::image                },
    { "inbox"                , fa::inbox                },
    { "indent"               , fa::indent               },
    { "industry"             , fa::industry             },
    { "info"                 , fa::info                 },
    { "infocircle"           , fa::infocircle           },
    { "inr"                  , fa::inr                  },
    { "instagram"            , fa::instagram            },
    { "institution"          , fa::institution          },
    { "internetexplorer"     , fa::internetexplorer     },
    { "intersex"             , fa::intersex             },
    { "ioxhost"              , fa::ioxhost              },
    { "italic"               , fa::italic               },
    { "joomla"               , fa::joomla               },
    { "jpy"                  , fa::jpy                  },
    { "jsfiddle"             , fa::jsfiddle             },
    { "key"                  , fa::key                  },
    { "keyboardo"            , fa::keyboardo            },
    { "krw"                  , fa::krw                  },
    { "language"             , fa::language             },
    { "laptop"               , fa::laptop               },
    { "lastfm"               , fa::lastfm               },
    { "lastfmsquare"         , fa::lastfmsquare         },
    { "leaf"                 , fa::leaf                 },
    { "leanpub"              , fa::leanpub              },
    { "legal"                , fa::legal                },
    { "lemono"               , fa::lemono               },
    { "leveldown"            , fa::leveldown            },
    { "levelup"              , fa::levelup              },
    { "lifebouy"             , fa::lifebouy             },
    { "lifebuoy"             , fa::lifebuoy             },
    { "lifering"             , fa::lifering             },
    { "lifesaver"            , fa::lifesaver            },
    { "lightbulbo"           , fa::lightbulbo           },
    { "linechart"            , fa::linechart            },
    { "link"                 , fa::link                 },
    { "linkedin"             , fa::linkedin             },
    { "linkedinsquare"       , fa::linkedinsquare       },
    { "fa_linux"             , fa::fa_linux             },
    { "list"                 , fa::list                 },
    { "listalt"              , fa::listalt              },
    { "listol"               , fa::listol               },
    { "listul"               , fa::listul               },
    { "locationarrow"        , fa::locationarrow        },
    { "lock"                 , fa::lock                 },
    { "longarrowdown"        , fa::longarrowdown        },
    { "longarrowleft"        , fa::longarrowleft        },
    { "longarrowright"       , fa::longarrowright       },
    { "longarrowup"          , fa::longarrowup          },
    { "magic"                , fa::magic                },
    { "magnet"               , fa::magnet               },
    { "mailforward"          , fa::mailforward          },
    { "mailreply"            , fa::mailreply            },
    { "mailreplyall"         , fa::mailreplyall         },
    { "male"                 , fa::male                 },
    { "map"                  , fa::map                  },
    { "mapmarker"            , fa::mapmarker            },
    { "mapo"                 , fa::mapo                 },
    { "mappin"               , fa::mappin               },
    { "mapsigns"             , fa::mapsigns             },
    { "mars"                 , fa::mars                 },
    { "marsdouble"           , fa::marsdouble           },
    { "marsstroke"           , fa::marsstroke           },
    { "marsstrokeh"          , fa::marsstrokeh          },
    { "marsstrokev"          , fa::marsstrokev          },
    { "maxcdn"               , fa::maxcdn               },
    { "meanpath"             , fa::meanpath             },
    { "medium"               , fa::medium               },
    { "medkit"               , fa::medkit               },
    { "meho"                 , fa::meho                 },
    { "mercury"              , fa::mercury              },
    { "microphone"           , fa::microphone           },
    { "microphoneslash"      , fa::microphoneslash      },
    { "minus"                , fa::minus                },
    { "minuscircle"          , fa::minuscircle          },
    { "minussquare"          , fa::minussquare          },
    { "minussquareo"         , fa::minussquareo         },
    { "mixcloud"             , fa::mixcloud             },
    { "mobile"               , fa::mobile               },
    { "mobilephone"          , fa::mobilephone          },
    { "modx"                 , fa::modx                 },
    { "money"                , fa::money                },
    { "moono"                , fa::moono                },
    { "mortarboard"          , fa::mortarboard          },
    { "motorcycle"           , fa::motorcycle           },
    { "mousepointer"         , fa::mousepointer         },
    { "music"                , fa::music                },
    { "navicon"              , fa::navicon              },
    { "neuter"               , fa::neuter               },
    { "newspapero"           , fa::newspapero           },
    { "objectgroup"          , fa::objectgroup          },
    { "objectungroup"        , fa::objectungroup        },
    { "odnoklassniki"        , fa::odnoklassniki        },
    { "odnoklassnikisquare"  , fa::odnoklassnikisquare  },
    { "opencart"             , fa::opencart             },
    { "openid"               , fa::openid               },
    { "opera"                , fa::opera                },
    { "optinmonster"         , fa::optinmonster         },
    { "outdent"              , fa::outdent              },
    { "pagelines"            , fa::pagelines            },
    { "paintbrush"           , fa::paintbrush           },
    { "paperplane"           , fa::paperplane           },
    { "paperplaneo"          , fa::paperplaneo          },
    { "paperclip"            , fa::paperclip            },
    { "paragraph"            , fa::paragraph            },
    { "paste"                , fa::paste                },
    { "pause"                , fa::pause                },
    { "pausecircle"          , fa::pausecircle          },
    { "pausecircleo"         , fa::pausecircleo         },
    { "paw"                  , fa::paw                  },
    { "paypal"               , fa::paypal               },
    { "pencil"               , fa::pencil               },
    { "pencilsquare"         , fa::pencilsquare         },
    { "pencilsquareo"        , fa::pencilsquareo        },
    { "percent"              , fa::percent              },
    { "phone"                , fa::phone                },
    { "phonesquare"          , fa::phonesquare          },
    { "photo"                , fa::photo                },
    { "pictureo"             , fa::pictureo             },
    { "piechart"             , fa::piechart             },
    { "piedpiper"            , fa::piedpiper            },
    { "piedpiperalt"         , fa::piedpiperalt         },
    { "pinterest"            , fa::pinterest            },
    { "pinterestp"           , fa::pinterestp           },
    { "pinterestsquare"      , fa::pinterestsquare      },
    { "plane"                , fa::plane                },
    { "play"                 , fa::play                 },
    { "playcircle"           , fa::playcircle           },
    { "playcircleo"          , fa::playcircleo          },
    { "plug"                 , fa::plug                 },
    { "plus"                 , fa::plus                 },
    { "pluscircle"           , fa::pluscircle           },
    { "plussquare"           , fa::plussquare           },
    { "plussquareo"          , fa::plussquareo          },
    { "poweroff"             , fa::poweroff             },
    { "print"                , fa::print                },
    { "producthunt"          , fa::producthunt          },
    { "puzzlepiece"          , fa::puzzlepiece          },
    { "qq"                   , fa::qq                   },
    { "qrcode"               , fa::qrcode               },
    { "question"             , fa::question             },
    { "questioncircle"       , fa::questioncircle       },
    { "quoteleft"            , fa::quoteleft            },
    { "quoteright"           , fa::quoteright           },
    { "ra"                   , fa::ra                   },
    { "random"               , fa::random               },
    { "rebel"                , fa::rebel                },
    { "recycle"              , fa::recycle              },
    { "reddit"               , fa::reddit               },
    { "redditalien"          , fa::redditalien          },
    { "redditsquare"         , fa::redditsquare         },
    { "refresh"              , fa::refresh              },
    { "registered"           , fa::registered           },
    { "remove"               , fa::remove               },
    { "renren"               , fa::renren               },
    { "reorder"              , fa::reorder              },
    { "repeat"               , fa::repeat               },
    { "reply"                , fa::reply                },
    { "replyall"             , fa::replyall             },
    { "retweet"              , fa::retweet              },
    { "rmb"                  , fa::rmb                  },
    { "road"                 , fa::road                 },
    { "rocket"               , fa::rocket               },
    { "rotateleft"           , fa::rotateleft           },
    { "rotateright"          , fa::rotateright          },
    { "rouble"               , fa::rouble               },
    { "rss"                  , fa::rss                  },
    { "rsssquare"            , fa::rsssquare            },
    { "rub"                  , fa::rub                  },
    { "ruble"                , fa::ruble                },
    { "rupee"                , fa::rupee                },
    { "safari"               , fa::safari               },
    { "save"                 , fa::save                 },
    { "scissors"             , fa::scissors             },
    { "scribd"               , fa::scribd               },
    { "search"               , fa::search               },
    { "searchminus"          , fa::searchminus          },
    { "searchplus"           , fa::searchplus           },
    { "sellsy"               , fa::sellsy               },
    { "send"                 , fa::send                 },
    { "sendo"                , fa::sendo                },
    { "server"               , fa::server               },
    { "share"                , fa::share                },
    { "sharealt"             , fa::sharealt             },
    { "sharealtsquare"       , fa::sharealtsquare       },
    { "sharesquare"          , fa::sharesquare          },
    { "sharesquareo"         , fa::sharesquareo         },
    { "shekel"               , fa::shekel               },
    { "sheqel"               , fa::sheqel               },
    { "shield"               , fa::shield               },
    { "ship"                 , fa::ship                 },
    { "shirtsinbulk"         , fa::shirtsinbulk         },
    { "shoppingbag"          , fa::shoppingbag          },
    { "shoppingbasket"       , fa::shoppingbasket       },
    { "shoppingcart"         , fa::shoppingcart         },
    { "signin"               , fa::signin               },
    { "signout"              , fa::signout              },
    { "signal"               , fa::signal               },
    { "simplybuilt"          , fa::simplybuilt          },
    { "sitemap"              , fa::sitemap              },
    { "skyatlas"             , fa::skyatlas             },
    { "skype"                , fa::skype                },
    { "slack"                , fa::slack                },
    { "sliders"              , fa::sliders              },
    { "slideshare"           , fa::slideshare           },
    { "smileo"               , fa::smileo               },
    { "soccerballo"          , fa::soccerballo          },
    { "sort"                 , fa::sort                 },
    { "sortalphaasc"         , fa::sortalphaasc         },
    { "sortalphadesc"        , fa::sortalphadesc        },
    { "sortamountasc"        , fa::sortamountasc        },
    { "sortamountdesc"       , fa::sortamountdesc       },
    { "sortasc"              , fa::sortasc              },
    { "sortdesc"             , fa::sortdesc             },
    { "sortdown"             , fa::sortdown             },
    { "sortnumericasc"       , fa::sortnumericasc       },
    { "sortnumericdesc"      , fa::sortnumericdesc      },
    { "sortup"               , fa::sortup               },
    { "soundcloud"           , fa::soundcloud           },
    { "spaceshuttle"         , fa::spaceshuttle         },
    { "spinner"              , fa::spinner              },
    { "spoon"                , fa::spoon                },
    { "spotify"              , fa::spotify              },
    { "square"               , fa::square               },
    { "squareo"              , fa::squareo              },
    { "stackexchange"        , fa::stackexchange        },
    { "stackoverflow"        , fa::stackoverflow        },
    { "star"                 , fa::star                 },
    { "starhalf"             , fa::starhalf             },
    { "starhalfempty"        , fa::starhalfempty        },
    { "starhalffull"         , fa::starhalffull         },
    { "starhalfo"            , fa::starhalfo            },
    { "staro"                , fa::staro                },
    { "steam"                , fa::steam                },
    { "steamsquare"          , fa::steamsquare          },
    { "stepbackward"         , fa::stepbackward         },
    { "stepforward"          , fa::stepforward          },
    { "stethoscope"          , fa::stethoscope          },
    { "stickynote"           , fa::stickynote           },
    { "stickynoteo"          , fa::stickynoteo          },
    { "stop"                 , fa::stop                 },
    { "stopcircle"           , fa::stopcircle           },
    { "stopcircleo"          , fa::stopcircleo          },
    { "streetview"           , fa::streetview           },
    { "strikethrough"        , fa::strikethrough        },
    { "stumbleupon"          , fa::stumbleupon          },
    { "stumbleuponcircle"    , fa::stumbleuponcircle    },
    { "subscript"            , fa::subscript            },
    { "subway"               , fa::subway               },
    { "suitcase"             , fa::suitcase             },
    { "suno"                 , fa::suno                 },
    { "superscript"          , fa::superscript          },
    { "support"              , fa::support              },
    { "table"                , fa::table                },
    { "tablet"               , fa::tablet               },
    { "tachometer"           , fa::tachometer           },
    { "tag"                  , fa::tag                  },
    { "tags"                 , fa::tags                 },
    { "tasks"                , fa::tasks                },
    { "taxi"                 , fa::taxi                 },
    { "television"           , fa::television           },
    { "tencentweibo"         , fa::tencentweibo         },
    { "terminal"             , fa::terminal             },
    { "textheight"           , fa::textheight           },
    { "textwidth"            , fa::textwidth            },
    { "th"                   , fa::th                   },
    { "thlarge"              , fa::thlarge              },
    { "thlist"               , fa::thlist               },
    { "thumbtack"            , fa::thumbtack            },
    { "thumbsdown"           , fa::thumbsdown           },
    { "thumbsodown"          , fa::thumbsodown          },
    { "thumbsoup"            , fa::thumbsoup            },
    { "thumbsup"             , fa::thumbsup             },
    { "ticket"               , fa::ticket               },
    { "times"                , fa::times                },
    { "timescircle"          , fa::timescircle          },
    { "timescircleo"         , fa::timescircleo         },
    { "tint"                 , fa::tint                 },
    { "toggledown"           , fa::toggledown           },
    { "toggleleft"           , fa::toggleleft           },
    { "toggleoff"            , fa::toggleoff            },
    { "toggleon"             , fa::toggleon             },
    { "toggleright"          , fa::toggleright          },
    { "toggleup"             , fa::toggleup             },
    { "trademark"            , fa::trademark            },
    { "train"                , fa::train                },
    { "transgender"          , fa::transgender          },
    { "transgenderalt"       , fa::transgenderalt       },
    { "trash"                , fa::trash                },
    { "trasho"               , fa::trasho               },
    { "tree"                 , fa::tree                 },
    { "trello"               , fa::trello               },
    { "tripadvisor"          , fa::tripadvisor          },
    { "trophy"               , fa::trophy               },
    { "truck"                , fa::truck                },
    { "fa_try"               , fa::fa_try               },
    { "tty"                  , fa::tty                  },
    { "tumblr"               , fa::tumblr               },
    { "tumblrsquare"         , fa::tumblrsquare         },
    { "turkishlira"          , fa::turkishlira          },
    { "tv"                   , fa::tv                   },
    { "twitch"               , fa::twitch               },
    { "twitter"              , fa::twitter              },
    { "twittersquare"        , fa::twittersquare        },
    { "umbrella"             , fa::umbrella             },
    { "underline"            , fa::underline            },
    { "undo"                 , fa::undo                 },
    { "university"           , fa::university           },
    { "unlink"               , fa::unlink               },
    { "unlock"               , fa::unlock               },
    { "unlockalt"            , fa::unlockalt            },
    { "unsorted"             , fa::unsorted             },
    { "upload"               , fa::upload               },
    { "usb"                  , fa::usb                  },
    { "usd"                  , fa::usd                  },
    { "user"                 , fa::user                 },
    { "usermd"               , fa::usermd               },
    { "userplus"             , fa::userplus             },
    { "usersecret"           , fa::usersecret           },
    { "usertimes"            , fa::usertimes            },
    { "users"                , fa::users                },
    { "venus"                , fa::venus                },
    { "venusdouble"          , fa::venusdouble          },
    { "venusmars"            , fa::venusmars            },
    { "viacoin"              , fa::viacoin              },
    { "videocamera"          , fa::videocamera          },
    { "vimeo"                , fa::vimeo                },
    { "vimeosquare"          , fa::vimeosquare          },
    { "vine"                 , fa::vine                 },
    { "vk"                   , fa::vk                   },
    { "volumedown"           , fa::volumedown           },
    { "volumeoff"            , fa::volumeoff            },
    { "volumeup"             , fa::volumeup             },
    { "warning"              , fa::warning              },
    { "wechat"               , fa::wechat               },
    { "weibo"                , fa::weibo                },
    { "weixin"               , fa::weixin               },
    { "whatsapp"             , fa::whatsapp             },
    { "wheelchair"           , fa::wheelchair           },
    { "wifi"                 , fa::wifi                 },
    { "wikipediaw"           , fa::wikipediaw           },
    { "windows"              , fa::windows              },
    { "won"                  , fa::won                  },
    { "wordpress"            , fa::wordpress            },
    { "wrench"               , fa::wrench               },
    { "xing"                 , fa::xing                 },
    { "xingsquare"           , fa::xingsquare           },
    { "ycombinator"          , fa::ycombinator          },
    { "ycombinatorsquare"    , fa::ycombinatorsquare    },
    { "yahoo"                , fa::yahoo                },
    { "yc"                   , fa::yc                   },
    { "ycsquare"             , fa::ycsquare             },
    { "yelp"                 , fa::yelp                 },
    { "yen"                  , fa::yen                  },
    { "youtube"              , fa::youtube              },
    { "youtubeplay"          , fa::youtubeplay          },
    { "youtubesquare"        , fa::youtubesquare        },
};


/// a specialized init function so font-awesome is loaded and initialized
/// this method return true on success, it will return false if the fnot cannot be initialized
/// To initialize QtAwesome with font-awesome you need to call this method
bool QtAwesome::initFontAwesome( )
{
    static int fontAwesomeFontId = -1;

    // only load font-awesome once
    if( fontAwesomeFontId < 0 ) {

        // The macro below internally calls "qInitResources_QtAwesome()". this initializes
        // the resource system. For a .pri project this isn't required, but when building and using a
        // static library the resource need to initialized first.
        ///
        // I've checked th qInitResource_* code and calling this method mutliple times shouldn't be any problem
        // (More info about this subject:  http://qt-project.org/wiki/QtResources)
        Q_INIT_RESOURCE(QtAwesome);

        // load the font file
        QFile res(":/fonts/fontawesome-4.5.0.ttf");
        if(!res.open(QIODevice::ReadOnly)) {
            qDebug() << "Font awesome font could not be loaded!";
            return false;
        }
        QByteArray fontData( res.readAll() );
        res.close();

        // fetch the given font
        fontAwesomeFontId = QFontDatabase::addApplicationFontFromData(fontData);
    }

    QStringList loadedFontFamilies = QFontDatabase::applicationFontFamilies(fontAwesomeFontId);
    if( !loadedFontFamilies.empty() ) {
        fontName_= loadedFontFamilies.at(0);
    } else {
        qDebug() << "Font awesome font is empty?!";
        fontAwesomeFontId = -1; // restore the font-awesome id
        return false;
    }

    // intialize the map
    QHash<QString, int>& m = namedCodepoints_;
    for (unsigned i = 0; i < sizeof(faNameIconArray)/sizeof(FANameIcon); ++i) {
      m.insert(faNameIconArray[i].name, faNameIconArray[i].icon);
    }

    return true;
}

void QtAwesome::addNamedCodepoint( const QString& name, int codePoint)
{
    namedCodepoints_.insert( name, codePoint);
}


/// Sets a default option. These options are passed on to the icon painters
void QtAwesome::setDefaultOption(const QString& name, const QVariant& value)
{
    defaultOptions_.insert( name, value );
}


/// Returns the default option for the given name
QVariant QtAwesome::defaultOption(const QString& name)
{
    return defaultOptions_.value( name );
}


// internal helper method to merge to option amps
static QVariantMap mergeOptions( const QVariantMap& defaults, const QVariantMap& override )
{
    QVariantMap result= defaults;
    if( !override.isEmpty() ) {
        QMapIterator<QString,QVariant> itr(override);
        while( itr.hasNext() ) {
            itr.next();
            result.insert( itr.key(), itr.value() );
        }
    }
    return result;
}


/// Creates an icon with the given code-point
/// <code>
///     awesome->icon( icon_group )
/// </code>
QIcon QtAwesome::icon(int character, const QVariantMap &options)
{
    // create a merged QVariantMap to have default options and icon-specific options
    QVariantMap optionMap = mergeOptions( defaultOptions_, options );
    optionMap.insert("text", QString( QChar(static_cast<int>(character)) ) );

    return icon( fontIconPainter_, optionMap );
}



/// Creates an icon with the given name
///
/// You can use the icon names as defined on http://fortawesome.github.io/Font-Awesome/design.html  withour the 'icon-' prefix
/// @param name the name of the icon
/// @param options extra option to pass to the icon renderer
QIcon QtAwesome::icon(const QString& name, const QVariantMap& options)
{
    // when it's a named codepoint
    if( namedCodepoints_.count(name) ) {
        return icon( namedCodepoints_.value(name), options );
    }


    // create a merged QVariantMap to have default options and icon-specific options
    QVariantMap optionMap = mergeOptions( defaultOptions_, options );

    // this method first tries to retrieve the icon
    QtAwesomeIconPainter* painter = painterMap_.value(name);
    if( !painter ) {
        return QIcon();
    }

    return icon( painter, optionMap );
}

/// Create a dynamic icon by simlpy supplying a painter object
/// The ownership of the painter is NOT transfered.
/// @param painter a dynamic painter that is going to paint the icon
/// @param optionmap the options to pass to the painter
QIcon QtAwesome::icon(QtAwesomeIconPainter* painter, const QVariantMap& optionMap )
{
    // Warning, when you use memoryleak detection. You should turn it of for the next call
    // QIcon's placed in gui items are often cached and not deleted when my memory-leak detection checks for leaks.
    // I'm not sure if it's a Qt bug or something I do wrong
    QtAwesomeIconPainterIconEngine* engine = new QtAwesomeIconPainterIconEngine( this, painter, optionMap  );
    return QIcon( engine );
}

/// Adds a named icon-painter to the QtAwesome icon map
/// As the name applies the ownership is passed over to QtAwesome
///
/// @param name the name of the icon
/// @param painter the icon painter to add for this name
void QtAwesome::give(const QString& name, QtAwesomeIconPainter* painter)
{
    delete painterMap_.value( name );   // delete the old one
    painterMap_.insert( name, painter );
}

/// Creates/Gets the icon font with a given size in pixels. This can be usefull to use a label for displaying icons
/// Example:
///
///    QLabel* label = new QLabel( QChar( icon_group ) );
///    label->setFont( awesome->font(16) )
QFont QtAwesome::font( int size )
{
    QFont font( fontName_);
    font.setPixelSize(size);
    return font;
}
